/**
 * 
 */
package switchviz.graphic;

import java.awt.Component;
import java.awt.Cursor;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLJPanel;
import javax.media.opengl.glu.GLU;

/**
 * @author Thomas
 *
 */
public abstract class GraphicEventListener implements GLEventListener, MouseListener, MouseMotionListener, KeyListener, MouseWheelListener
{	
	private float[] _bgcolor = {0.0f, 0.0f, 0.0f};
	private GLU _glu = null;
	protected float _camPosX = 0.0f;
	protected float _camPosZ = 2.5f;
	protected float _camPosY = 0.0f;
	protected float _camGazeX = 0.0f;
	protected float _camGazeY = 0.0f;
	protected float _camGazeZ = -1.0f;
	protected float _cellRotX = 0.0f;
	protected float _cellRotY = 0.0f;
	protected int _mouseFixX = 0;
	protected int _mouseFixY = 0;
	private float _sensibility = 10.0f;
	protected int _screenwidth = 1;
	protected int _screenheight = 1;
	
	public void setBGColor(float[] bgcolor)
	{
		_bgcolor = bgcolor;
	}
	
	public void display(GLAutoDrawable drawable)
	{
		GL gl = drawable.getGL();

		if ((drawable instanceof GLJPanel) &&
		        !((GLJPanel) drawable).isOpaque() &&
		        ((GLJPanel) drawable).shouldPreserveColorBufferIfTranslucent())
		{
			gl.glClear(GL.GL_DEPTH_BUFFER_BIT);
		} 
		else 
			gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
	
		
		gl.glLoadIdentity();
		
		GLU glu = new GLU();
		glu.gluLookAt(_camPosX, _camPosY, _camPosZ, _camGazeX, _camGazeY, _camGazeZ, 0.0, 1.0, 0.0);
	}
	
	public void rotateEachCell(GL gl)
	{
		if(_cellRotX == 0 && _cellRotY == 0) return;
		gl.glRotatef(_cellRotX, 1.0f, 0.0f, 0.0f);
		gl.glRotatef(_cellRotY, 0.0f, 1.0f, 0.0f);
	}
	
	
	public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged)
	{
	}

	public void init(GLAutoDrawable drawable)
	{
		GL gl = drawable.getGL();
        gl.setSwapInterval(1);
        gl.glClearColor(_bgcolor[0], _bgcolor[1], _bgcolor[2], 0.0f);
        gl.glEnable(GL.GL_DEPTH_TEST);
		gl.glEnable(GL.GL_COLOR_MATERIAL);
		
        //gl.glMatrixMode(GL.GL_MODELVIEW);
		
		
//		gl.glEnable(GL.GL_POINT_SMOOTH);

		float[] pda = {0.007f, 0.005f, 0.05f};
		gl.glPointParameterfvARB(GL.GL_POINT_DISTANCE_ATTENUATION, pda, 0);

        gl.glEnable(GL.GL_BLEND);
		gl.glBlendFunc(GL.GL_SRC_ALPHA,GL.GL_ONE_MINUS_SRC_ALPHA);
	}

	public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height)
	{
		GL gl = drawable.getGL();
	      
	    if (height <= 0) // avoid a divide by zero error!
	    	  height = 1;
	    	    
	    gl.glViewport(0, 0, width, height);
		GLU glu = new GLU();
		
		gl.glMatrixMode(GL.GL_PROJECTION); 
		gl.glLoadIdentity(); 
		glu.gluPerspective(50.0, width / height, 0.1, 100.0); 
		gl.glMatrixMode(GL.GL_MODELVIEW); 
		//gl.glLoadIdentity(); 
		_screenwidth = width;
		_screenheight = height;
		
	}
	
	public void mousePressed(MouseEvent evt) 
	{
		_mouseFixX = evt.getX();
		_mouseFixY = evt.getY();
	}

	public void mouseDragged(MouseEvent evt) 
	{
		((Component)evt.getSource()).setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
		if(evt.isShiftDown())
		{
			_cellRotY = _cellRotY + (-evt.getX() + _mouseFixX) * 16 * _sensibility / _screenwidth;
			_cellRotX = _cellRotX + (-evt.getY() + _mouseFixY) * 16 * _sensibility / _screenheight;
		}
		else if(evt.isControlDown())
		{
			_camPosX = _camPosX + (evt.getX() - _mouseFixX) * _sensibility / _screenwidth;
			_camPosZ = _camPosZ + (-evt.getY() + _mouseFixY) * _sensibility / _screenheight;
		}
		else
		{
			_camGazeX = _camGazeX - (evt.getX() - _mouseFixX) * _camPosZ * _sensibility  / _screenwidth / 10.5f;
			_camGazeY = _camGazeY - (-evt.getY() + _mouseFixY) * _camPosZ * _sensibility  / _screenheight / 10.5f;
			_camPosX = _camPosX - (evt.getX() - _mouseFixX) * _camPosZ * _sensibility  / _screenwidth / 10.5f;
			_camPosY = _camPosY - (-evt.getY() + _mouseFixY) * _camPosZ * _sensibility  / _screenheight / 10.5f;
		}
		_mouseFixX = evt.getX();
		_mouseFixY = evt.getY();
	}

	public void mouseReleased(MouseEvent evt) 
	{
		((Component)evt.getSource()).setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
	}
	
	public void mouseWheelMoved(MouseWheelEvent evt) 
	{
		_camPosZ = _camPosZ + (evt.getWheelRotation()) * _sensibility * 5.0f / _screenheight;
	}
	
	protected GLU getGlu()
	{
		if (_glu == null)
			_glu = new GLU();
		return _glu;
	}
	
	public void mouseMoved(MouseEvent evt) {}
	public void mouseClicked(MouseEvent evt) {}
	public void mouseEntered(MouseEvent evt) {}
	public void mouseExited(MouseEvent evt) {}
	
	public void keyPressed(KeyEvent evt) {}
	public void keyReleased(KeyEvent evt) {}
	public void keyTyped(KeyEvent evt) {}
}
